package statement;

import util.Reference;
import util.Scope;
import util.Selector;
import util.Type;
import exception.ExpressionException;
import exception.NoMoreStepsException;
import exception.StatementExecutionException;
import expression.Expression;
import expression.primary.Ident;

public class AssignmentStatement implements Statement {
	
	private Ident ident;
	private Expression expression;
	private Scope scope;
	private boolean done;
	
	public AssignmentStatement(Scope scope, Expression expression, Ident ident) {
		this.expression = expression;
		this.ident = ident;
		this.scope = scope;
		this.done = false;
		
		//System.out.println("ddd " + ident.getName());
	}

	@Override
	public void execute() throws StatementExecutionException, NoMoreStepsException {
		try {
			if(!ident.getReference().getType().getName().equals(expression.getResultType().getName())) {
				throw new StatementExecutionException("Niezgodne typy:\nzmienna: " + ident.getReference().getType() + "\nwyrazenie: " + expression.getResultType());
			}
		} catch (ExpressionException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch(Exception e) {
			e.printStackTrace();
		}
		try {
			while(true) {
				nextStep();
			}
		} catch (NoMoreStepsException e) {
			
		}
		
	}

	@Override
	public void nextStep() throws StatementExecutionException, NoMoreStepsException {
		if(done) {
			throw new NoMoreStepsException();
		}
		try {
//			System.out.println("APRZED"+scope);
			Reference ref = scope.getReference(ident.getName());
			if(ident.getSelectors().size() > 0)
				for(Selector sel : ident.getSelectors()){
					if(sel.getType().compareTo("index") == 0){
						Object[] array = (Object[])ref.getValue();
						array[(Integer)sel.getValue()] = expression.evaluate();
					}
				}
			else
				ref.setValue(expression.evaluate());
//			System.out.println("APO"+scope);
		} catch (ExpressionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		done = true;
	}

	public String toString() {
		return "AssignmentStatement: [ ident: " + this.ident + ", expression: " + this.expression + "]";
	}
	
	public void reset() {
		done = false;
	}

}
